package busterminal.entity;

import busterminal.entity.service.DaysOfWeek;
import busterminal.entity.service.Time;
import busterminal.exception.BusinessException;
import java.util.List;

/**
 * Пункт расписания (реализация)
 */
public class ScheduledItemImplementation extends AbstractEntityImplementation implements ScheduledItem {

    /**
     * Маршрут, по которому осуществляется рейс
     */
    private Route route;
    /**
     * Время отправления
     */
    private Time departureTime;
    /**
     * Время прибытия
     */
    private Time arrivalTime;
    /**
     * Время в пути
     */
    private Time travelTime;
    /**
     * Время отправления с конечного пункта
     */
    private Time departureTimeFromEndPoint;
    /**
     * Время прибытия на автовокзал
     */
    private Time arrivalTimeToBusTerminal;
    /**
     * Дни недели осуществления рейсов по маршруту
     */
    private List<DaysOfWeek> routingDays;
    /**
     * Номер платформы, с которой будет отправляться автобус по определённому маршруту
     */
    private int platformNumber;

    /**
     * Конструктор по умолчанию
     */
    public ScheduledItemImplementation() {
    }

    /**
     * Параметризованный конструктор
     * @param route маршрут, по которому осуществляется рейс
     * @param departureTime время отправления
     * @param arrivalTime время прибытия
     * @param departureTimeFromEndPoint время отправления с конечного пункта
     * @param arrivalTimeToBusTerminal время прибытия на автовокзал
     * @param routingDays дни недели осуществления рейсов по маршруту
     * @param platformNumber номер платформы, с которой будет отправляться автобус по определённому маршруту
     * @throws BusinessException время отправления позже времени прибытия
     */
    public ScheduledItemImplementation(Route route, Time departureTime, Time arrivalTime, Time departureTimeFromEndPoint, Time arrivalTimeToBusTerminal, List<DaysOfWeek> routingDays, int platformNumber) throws BusinessException {
        this.route = route;
        this.departureTime = departureTime;
        this.arrivalTime = arrivalTime;
        this.travelTime = arrivalTime.getDifference(departureTime);
        this.departureTimeFromEndPoint = departureTimeFromEndPoint;
        this.arrivalTimeToBusTerminal = arrivalTimeToBusTerminal;
        this.routingDays = routingDays;
        this.platformNumber = platformNumber;
    }

    /**
     * Получить время прибытия
     * @return время прибытия
     */
    @Override
    public Time getArrivalTime() {
        return arrivalTime;
    }

    /**
     * Установить время прибытия
     * @param arrivalTime время прибытия
     */
    @Override
    public void setArrivalTime(Time arrivalTime) {
        this.arrivalTime = arrivalTime;
    }

    /**
     * Получить время прибытия на автовокзал
     * @return время прибытия на автовокзал
     */
    @Override
    public Time getArrivalTimeToBusTerminal() {
        return arrivalTimeToBusTerminal;
    }

    /**
     * Установить время прибытия на автовокзал
     * @param arrivalTimeToBusTerminal время прибытия на автовокзал
     */
    @Override
    public void setArrivalTimeToBusTerminal(Time arrivalTimeToBusTerminal) {
        this.arrivalTimeToBusTerminal = arrivalTimeToBusTerminal;
    }

    /**
     * Получить время отправления
     * @return время отправления
     */
    @Override
    public Time getDepartureTime() {
        return departureTime;
    }

    /**
     * Установить время отправления
     * @param departureTime время отправления
     */
    @Override
    public void setDepartureTime(Time departureTime) {
        this.departureTime = departureTime;
    }

    /**
     * Получить время отправления с конечного пункта
     * @return время отправления с конечного пункта
     */
    @Override
    public Time getDepartureTimeFromEndPoint() {
        return departureTimeFromEndPoint;
    }

    /**
     * Установить время отправления с конечного пункта
     * @param departureTimeFromEndPoint время отправления с конечного пункта
     */
    @Override
    public void setDepartureTimeFromEndPoint(Time departureTimeFromEndPoint) {
        this.departureTimeFromEndPoint = departureTimeFromEndPoint;
    }

    /**
     * Получить номер платформы, с которой будет отправляться автобус по определённому маршруту
     * @return номер платформы, с которой будет отправляться автобус по определённому маршруту
     */
    @Override
    public int getPlatformNumber() {
        return platformNumber;
    }

    /**
     * Установить номер платформы, с которой будет отправляться автобус по определённому маршруту
     * @param platformNumber номер платформы, с которой будет отправляться автобус по определённому маршруту
     */
    @Override
    public void setPlatformNumber(int platformNumber) {
        this.platformNumber = platformNumber;
    }

    /**
     * Получить маршрут, по которому осуществляется рейс
     * @return маршрут, по которому осуществляется рейс
     */
    @Override
    public Route getRoute() {
        return route;
    }

    /**
     * Установить маршрут, по которому осуществляется рейс
     * @param route маршрут, по которому осуществляется рейс
     */
    @Override
    public void setRoute(Route route) {
        this.route = route;
    }

    /**
     * Получить дни недели осуществления рейсов по маршруту
     * @return дни недели осуществления рейсов по маршруту
     */
    @Override
    public List<DaysOfWeek> getRoutingDays() {
        return routingDays;
    }

    /**
     * Получить строку, содержащую дни недели осуществления рейсов по маршруту
     * @return строку, содержащая дни недели осуществления рейсов по маршруту
     */
    @Override
    public String getRoutingDaysString() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < routingDays.size(); i++) {
            if (i != routingDays.size() - 1) {
                sb.append(routingDays.get(i).toString()).append(", ");
            } else {
                sb.append(routingDays.get(i).toString());
            }
        }
        return sb.toString();
    }

    /**
     * Установить дни недели осуществления рейсов по маршруту
     * @param routingDays дни недели осуществления рейсов по маршруту
     */
    @Override
    public void setRoutingDays(List<DaysOfWeek> routingDays) {
        this.routingDays = routingDays;
    }

    /**
     * Получить время в пути
     * @return время в пути
     */
    @Override
    public Time getTravelTime() {
        return travelTime;
    }

    /**
     * Установить время в пути на основе времени прибытия и отправления
     * @throws BusinessException время отправления позже времени прибытия
     */
    @Override
    public void setTravelTime() throws BusinessException {
        travelTime = arrivalTime.getDifference(departureTime);
    }

    /**
     * Метод, возвращающий текстовое представление объекта
     * @return текстовое представление объекта
     */
    @Override
    public String toString() {
        return "ScheduledItemImplementation{" + "id=" + getId() + ", route=" + route + ", departureTime=" + departureTime + ", arrivalTime=" + arrivalTime + ", travelTime=" + travelTime + ", departureTimeFromEndPoint=" + departureTimeFromEndPoint + ", arrivalTimeToBusTerminal=" + arrivalTimeToBusTerminal + ", routingDays=" + routingDays + ", platformNumber=" + platformNumber + '}';
    }
}
